#!/usr/bin/perl
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 2000,2002 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
# @(#)13   1.10   src/csm/dms/cmds/csmconfig.perl, dms, csm_rpyxh, rpyxht1f3 7/22/02 13:46:47

use strict;
use locale;
BEGIN
  {
	# this enables us to redirect where it looks for other CSM files during development
	$::csmroot = $ENV{'CSM_ROOT'} ? $ENV{'CSM_ROOT'} : '/opt/csm';
	$::csmpm = "$::csmroot/pm";
	$::csmbin = "$::csmroot/bin";
  }
use lib $::csmpm;
use Getopt::Std;
require NodeUtils;
require InstallDefs;
require InstallUtils;

#nlstodo:  add these to nodecmds.msg.  Also add -Z to usage and make -L arg optional.
$::MSGS = {
		   IMsgBACKUP => 'Backing up file %1$s to %2$s\n',
		   EMsgALREADY_TAB => 'A try and buy license is already installed.  Run csmconfig without arguments to see the expiration date of the license.\n',
		   EMsgALREADY_FULL => 'A full license is already installed.  Not installing the try and buy license.\n',
		   EMsgNOT_ACCEPTED => 'License agreement not accepted - can not install license key.\n',
		  };

#nlstodo: add -d option to IMsgCsmconfigUsage
# For the usage, see nodecmds.msg
sub usage { NodeUtils->message('I', 'IMsgCsmconfigUsage');  exit (scalar(@_) ? $_[0] : 1); }

$::MSGCAT = 'nodecmds.cat';
$::MSGMAPPATH = "$::csmroot/msgmaps";
$::MSGSET = 'csmconfig';     # setting this explicitly so it will work with the old dmsctrl link

# Parse the cmd line args and check them
if (! getopts('hvVu:m:s:r:R:Ld:Z:') ) { &usage; }
if ($::opt_h) { &usage(0); }
my $setflags = defined($::opt_u) + defined($::opt_m) + defined($::opt_s) + defined($::opt_r) + defined($::opt_R);
if ((defined($::opt_V) + defined($::opt_L) + defined($::opt_d) + defined($::opt_Z) + ($setflags>0 || (scalar(@ARGV)>0&&!defined($::opt_L)))) > 1 ) { &usage; }

$::VERBOSE = $::opt_v;
$ENV{'CT_MANAGEMENT_SCOPE'} = 1;      # set local scope because we only want the local DmsCtrl class

#my $rc=0;
if ($::opt_V)           # display CSM version
  {
	my $version = InstallUtils->get_CSMVersion('csm.server', 1);
	if (!defined($version)) { exit 2; }     # the above function already displayed an error msg
	print "$version\n";
  }

elsif (defined($::opt_L))      # install a license key file
  {
	# Set directory and file names
	my $licdir = '/var/opt/csm/lic';   # Where the ECF files should be put
	my $nlfile = "$licdir/nodelock";
	my $infile;      # file specified by user or the default
	
	if (scalar(@ARGV))         # they specified an ECF file
	  {
		$infile = $ARGV[0];
		if (!(-r $infile)) { NodeUtils->message('E1','EMsgBAD_KEYFILE', $infile); }
	  }
	else            # using default ECF file shipped with csm.server
	  {
		$infile = "$licdir/default";
		if (!(-r $infile)) { NodeUtils->message('E1','EMsgBAD_KEYFILE', ''); }
	  }
		
	# Determine the type of ECF
	my $tryandbuy = NodeUtils->runcmd("/bin/grep TryAndBuy $infile");
	my $lumfile = 'csmlum.lic';
	my $tab = 0;
	if ($tryandbuy =~ /TryAndBuy\s*=\s*Yes/) { $lumfile = 'csmlum.tab';  $tab = 1; }

	# Leave it they have already installed a try-and-buy
	if ($tab)
	  {
		if (-f "$licdir/csmlum.lic") { NodeUtils->msg($::MSGS,'W2','EMsgALREADY_FULL'); }   # we do not let them install a try-and-buy over a full
		if (-f $nlfile) { NodeUtils->msg($::MSGS,'W2','EMsgALREADY_TAB'); }   # we do not let them install a try-and-buy again
	  }

	# Display license agreement
	if (!&displayLicenseAgreement($tab)) { NodeUtils->msg($::MSGS,'W3','EMsgNOT_ACCEPTED'); }
	
	# Make backup of nodelock file if it exists and this is a full license
	if (!$tab && -f $nlfile)
	  {
		#NodeUtils->msg($::MSGS,'V','IMsgBACKUP', $nlfile, "$nlfile.backup");
		rename($nlfile, "$nlfile.backup") or NodeUtils->messageFromCat($::MSGCAT, $::MSGMAPPATH, 'NodeUtils', 'E' . $!/1,'EMsgCMD_FAILED', $!/1, "rename($nlfile, $nlfile.backup)", $!);
	  }

	# Move the ECF file into place so DMSRM will pick it up
	$lumfile = "$licdir/$lumfile";
	if (-f $lumfile)
	  {
		#NodeUtils->msg($::MSGS,'V','IMsgBACKUP', $lumfile, "$lumfile.backup");
		rename($lumfile, "$lumfile.backup") or NodeUtils->messageFromCat($::MSGCAT, $::MSGMAPPATH, 'NodeUtils', 'E' . $!/1,'EMsgCMD_FAILED', $!/1, "rename($lumfile, $lumfile.backup)", $!);
	  }
	if (!(-d $licdir)) { NodeUtils->runcmd("/bin/mkdir -p $licdir"); }
	NodeUtils->runcmd("/bin/cp $infile $lumfile");

	# Refresh DmsCtrl so that it picks up the ECF file and creates the nodelock file
	# The logic of DMSRM is that when it starts up or is refresh, if there is not a nodelock
	# file it will look for the ECF file /var/opt/csm/lic and create the nodelock file.
	NodeUtils->runrmccmd('refrsrc-api', '-c IBM.DmsCtrl');
  }

elsif (defined($::opt_Z))      # display license agreement
  {
	&displayLicenseAgreement($::opt_Z);
  }

elsif (defined($::opt_d))      # display just one attr
  {
	my $outref = NodeUtils->runrmccmd('lsrsrc-api', '', "-s IBM.DmsCtrl::::$::opt_d");
	print "$$outref[0]\n";
  }

elsif ($setflags || scalar(@ARGV)>0)           # set 1 or more of the values
  {
	my %attrs;
	# 1st process the attr=val pairs
	foreach my $a (@ARGV)
	  {
		# Note: we allow a null value
		my ($at, $val) = $a =~ /^\s*(\S+?)\s*=\s*(\S*.*)$/;
		if (!defined($at)) { NodeUtils->messageFromCat($::MSGCAT, $::MSGMAPPATH, 'createnode', 'E1','EMsgBAD_ATTR_VAL_FORM'); }
		$attrs{$at} = $val;
	  }
	
	# Now process specific flags
	if (defined($::opt_u)) { $attrs{'AddUnrecognizedNodes'} = $::opt_u; }
	if (defined($::opt_R)) { $attrs{'SetupRemoteShell'} = $::opt_R; }
	if (defined($::opt_r)) { $attrs{'RemoteShell'} = $::opt_r; }
	if (defined($::opt_m)) { $attrs{'ClusterTM'} = $::opt_m; }
	if (defined($::opt_s)) { $attrs{'ClusterSNum'} = $::opt_s; }

	# Now check the values
	my $r;						# this reduces the # of hash lookups
	if (defined($r=$attrs{'AddUnrecognizedNodes'}))
	  {
		if ($r =~ /yes|1/i) { $attrs{'AddUnrecognizedNodes'} = 1; }
		elsif ($r =~ /no|0/i) { $attrs{'AddUnrecognizedNodes'} = 0; }
		else { NodeUtils->message('E1','EMsgBAD_U_VALUE', 'AddUnrecognizedNodes'); }
	  }
	if (defined($r=$attrs{'SetupRemoteShell'}))
	  {
		if ($r =~ /yes|1/i) { $attrs{'SetupRemoteShell'} = 1; }
		elsif ($r =~ /no|0/i) { $attrs{'SetupRemoteShell'} = 0; }
		else { NodeUtils->message('E1','EMsgBAD_U_VALUE', 'SetupRemoteShell'); }
	  }
	if (defined($r=$attrs{'RemoteShell'}))
	  {
		if (!(-x $r)) { NodeUtils->message('E1','EMsgBAD_SHELL', $r); }
	  }
	if (defined($r=$attrs{'ClusterTM'}))
	  {
		if (!($r =~ /^\s*\d{4}-\d{3}\s*$/)) { NodeUtils->message('E1','EMsgBAD_MODEL', $r); }
	  }

	# Build the cmd string
	my $attrstr = '';
	foreach my $k (keys %attrs)
	  {
		my $val = $attrs{$k};
		if (!length($val)) { $val = "''"; }	# mkrsrc-api needs something for the value
		$val = NodeUtils->quote($val);    # Put quotes around the value to protect spaces or weird chars
		$attrstr .= "::${k}::$val";
	  }
	my $outref = NodeUtils->runrmccmd('chrsrc-api', '-i', qq(-s IBM.DmsCtrl::$attrstr));
  }

else         # display all values
  {
	my $outref = NodeUtils->runrmccmd('lsrsrc-api', "-D ':|:' -n", "-s IBM.DmsCtrl::::'*p0x0020'");
	
	# takes the alternating attrs and values and puts them in the hash correctly
	my %attrs = split(/:\|:/, $$outref[0]);

	delete $attrs{'NodeNameList'};       # do not want to display this one
	
	# Give explanations for some of the attributes
	&getMeanings();
	#my %names;
	my $r;						# this reduces the # of hash lookups
	if (defined($r=$attrs{'MaxNumNodesInDomain'}))
	  {
		if ($r == -1) { $attrs{'MaxNumNodesInDomain'} .= " $::UNLIMITED"; }
		#$names{'MaxNumNodesInDomain'} = NodeUtils->getMessage('IMsgMAX_NODES_VALUE');
	  }
	if (defined($r=$attrs{'AddUnrecognizedNodes'}))
	  {
		$attrs{'AddUnrecognizedNodes'} .= $r ? " $::YES" : " $::NO";
		#$names{'AddUnrecognizedNodes'} = NodeUtils->getMessage('IMsgUNRECOGNIZE_VALUE');
	  }
	# Now display the rest of the attributes, sorted
	foreach my $k (sort keys %attrs)
	  {
		#my $name = defined($names{$k}) ? $names{$k} : $k;
		print " $k = $attrs{$k}\n";
	  }
  }

exit;


# Gets a list of the words: (yes) (no) (on) (off) (unknown)
# and puts them in global vars
sub getMeanings
  {
	# Check if we already got them so we do not do it every time.
	if (!defined($::YES))
	  {
		($::YES, $::NO, $::UNLIMITED) = split(/\|/, NodeUtils->getMessage('IMsgCsmconfigATTRIBUTE_MEANINGS'));
	  }
  }


sub displayLicenseAgreement
  {
	my $tab = shift;
	my $rc = InstallUtils->invokeLAP($tab ? 'tab' : 'full');
	return ($rc == 9);
  }
